package com.ffcs.cn.action.base.tree;


import com.supermap.desktop.controls.ui.UICommonToolkit;
import com.supermap.desktop.controls.ui.controls.SmDialog;
import com.supermap.desktop.controls.ui.controls.scrollPanel.SmNoBorderScrollPanel;
import com.supermap.desktop.core.Application;
import com.supermap.desktop.core.copycutpaste.SmTransferable;
import com.supermap.desktop.core.ui.controls.GridBagConstraintsHelper;
import com.supermap.desktop.core.utilties.LogUtilities;
import com.ffcs.cn.DevelopProperties;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class DialogJTreeSimpleDrag extends SmDialog {
	private JTree tree;
	private JPanel jPanel;
	// 定义拖拽的数据类型，不同数据节点可以用不同的定义，方便接收推拽的控件判别是不是自己想要的数据
	public static final DataFlavor TREE_SIMPLE_DRAG_STRING = new DataFlavor(DialogJTreeSimpleDrag.class, "JTreeSimpleDragString");

	public DialogJTreeSimpleDrag() {
		//设置标题
		setTitle("拖拽简单示例");
		//初始化使用控件
		initComponents();
		//初始化布局，并添加控件
		initLayout();
		// 初始化拖拽
		initDrag();
		//设置初始化窗口大小
		Dimension dimension = new Dimension(350, 560);
		setSize(dimension);
		//设置最小窗口
		setMinimumSize(dimension);
	}

	private void initComponents() {
		//创建节点
		DefaultMutableTreeNode workspaceNode = new DefaultMutableTreeNode("工作空间(将文件拖拽到数据源节点)");

		DefaultMutableTreeNode datasourceNode = new DefaultMutableTreeNode(DevelopProperties.getString("String_DatasourceName"));
		//添加子节点
		datasourceNode.add(new DefaultMutableTreeNode("DataSource1"));
		datasourceNode.add(new DefaultMutableTreeNode("DataSource2"));
		datasourceNode.add(new DefaultMutableTreeNode("DataSource3"));

		DefaultMutableTreeNode mapNode = new DefaultMutableTreeNode("地图");
		mapNode.add(new DefaultMutableTreeNode("Map1"));
		mapNode.add(new DefaultMutableTreeNode("Map2"));
		mapNode.add(new DefaultMutableTreeNode("Map3"));

		DefaultMutableTreeNode layoutNode = new DefaultMutableTreeNode("布局");
		layoutNode.add(new DefaultMutableTreeNode("Layout1"));
		layoutNode.add(new DefaultMutableTreeNode("Layout2"));
		layoutNode.add(new DefaultMutableTreeNode("Layout3"));

		workspaceNode.add(datasourceNode);
		workspaceNode.add(mapNode);
		workspaceNode.add(layoutNode);

		//创建树
		this.tree = new JTree(workspaceNode);
		//根节点显示折叠按钮
		this.tree.setShowsRootHandles(true);
		this.jPanel = new JPanel();
	}

	private void initLayout() {
		//设置布局为 GridBagLayout 布局
		this.setLayout(new GridBagLayout());
		//将 tree 添加到无边框的滚动面板中
		SmNoBorderScrollPanel scrollPanelTree = new SmNoBorderScrollPanel(tree);
		//添加滚动面板
		this.add(scrollPanelTree, new GridBagConstraintsHelper(0, 0, 1, 1).setWeight(1, 1)
				.setInsets(GridBagConstraintsHelper.FRAME_CONTROL_GAP, GridBagConstraintsHelper.FRAME_CONTROL_GAP, 0, GridBagConstraintsHelper.CONTROLS_GAP)
				.setFill(GridBagConstraints.BOTH));

		this.jPanel.setBorder(BorderFactory.createTitledBorder(DevelopProperties.getString("String_DragTreeNodeToHere")));
		// 添加JPanel
		this.add(this.jPanel, new GridBagConstraintsHelper(0, 1, 1, 1).setWeight(1, 1)
				.setInsets(GridBagConstraintsHelper.CONTROLS_GAP, GridBagConstraintsHelper.FRAME_CONTROL_GAP, GridBagConstraintsHelper.FRAME_CONTROL_GAP, GridBagConstraintsHelper.CONTROLS_GAP)
				.setFill(GridBagConstraints.BOTH));
	}

	private void initDrag() {
		this.tree.setDragEnabled(true);// 开启拖拽
		this.tree.setTransferHandler(new TreeTransferHandler());// 树绑定TransferHandler，可以自定义从树拖拽出去的内容，方便拖拽接收目标解析
		new DropTarget(this.tree, new TreeDropTargetAdapter());// 树绑定拖拽目标事件，绑定后树可以解析拖拽东西到树的行为
		new DropTarget(this.jPanel, new PanelDropTargetAdapter());// Panel绑定拖拽目标事件，绑定后Panel可以解析拖拽东西到Panel的行为
	}


	class TreeDropTargetAdapter extends DropTargetAdapter {

		// 判断是否支持拖拽
		private boolean isDropAcceptable(DropTargetDropEvent event) {
			return (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0;
		}

		@Override
		public void drop(DropTargetDropEvent dtde) {
			if (!isDropAcceptable(dtde)) {
				dtde.rejectDrop();
				return;
			}
			Transferable transferable = null;
			try {
				transferable = dtde.getTransferable();
			} catch (Exception e) {
				LogUtilities.error(e.getMessage(), e);
			}
			if (transferable == null) {
				return;
			}
			// 接收外部拖拽来的数据
			dtde.acceptDrop(DnDConstants.ACTION_REFERENCE);
			try {
				DataFlavor[] dataFlavors = transferable.getTransferDataFlavors();
				if (transferable.isDataFlavorSupported(dataFlavors[0])) {
					for (DataFlavor dataFlavor : dataFlavors) {
						if (dataFlavor == null) {
							continue;
						}
						// 如果拖入的是文件格式
						if (dataFlavor.equals(DataFlavor.javaFileListFlavor)) {
							Point location = dtde.getLocation();
							TreePath pathForLocation = tree.getPathForLocation(location.x, location.y);// 获取鼠标所在位置的树节点
							List<File> filelList = (List<File>) transferable.getTransferData(dataFlavor);
							if (pathForLocation != null && pathForLocation.getLastPathComponent() instanceof DefaultMutableTreeNode) {
								DefaultMutableTreeNode mutableTreeNode = (DefaultMutableTreeNode) pathForLocation.getLastPathComponent();
								for (File file : filelList) {
									//创建新节点
									DefaultMutableTreeNode node = new DefaultMutableTreeNode(file.getName() + (mutableTreeNode.getChildCount() + 1));
									//插入新节点
									((DefaultTreeModel) tree.getModel()).insertNodeInto(node, mutableTreeNode, mutableTreeNode.getChildCount());
								}
							}
						}
					}
				}
			} catch (Exception e) {
				Application.getActiveApplication().getOutput().output(e);
			}
		}
	}

	class TreeTransferHandler extends TransferHandler {

		@Override
		public int getSourceActions(JComponent c) {
			return MOVE;// 支持移动，继而可以拖拽树节点
		}

		@Override
		protected Transferable createTransferable(JComponent c) {
			// 移动时（拖拽）会进入这里，创建一个Transferable持有拖拽的数据
			if (null != tree.getLastSelectedPathComponent()) {
				DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
				if (null != treeNode && null != treeNode.getUserObject()) {
					DefaultMutableTreeNode[] treeNodes = new DefaultMutableTreeNode[tree.getSelectionCount()];
					TreePath[] selectionPaths = tree.getSelectionPaths();
					if (selectionPaths != null) {
						for (int i = 0; i < selectionPaths.length; i++) {
							treeNodes[i] = (DefaultMutableTreeNode) selectionPaths[i].getLastPathComponent();
						}
					}
					return new TreeTransferable(treeNodes);
				}
			}
			return null;
		}
	}

	class TreeTransferable extends SmTransferable {

		private final DefaultMutableTreeNode[] treeNodes;
		private Object[] data = null;

		public TreeTransferable(DefaultMutableTreeNode... treeNodes) {
			this.treeNodes = treeNodes;
			this.data = new Object[this.treeNodes.length];
			fillArrays();
		}

		private void fillArrays() {
			DefaultMutableTreeNode treeNode = this.treeNodes[0];
			Object treeNodeUserObject = treeNode.getUserObject();
			// 可以根据不同的数据节点使用不同的类型，该Demo统一都是String，所以都使用TREE_SIMPLE_DRAG_STRING
			if (treeNodeUserObject instanceof String) {
				for (int i = 0; i < this.treeNodes.length; i++) {
					String userObject = (String) this.treeNodes[i].getUserObject();
					this.data[i] = userObject;// 填充持有的数据
				}
				this.dataFlavor = TREE_SIMPLE_DRAG_STRING;// 设置数据类型
			}
		}

		// 获取持有的数据
		@Override
		public Object getData() {
			return this.data;
		}
	}

	class PanelDropTargetAdapter extends DropTargetAdapter {

		@Override
		public void drop(DropTargetDropEvent dtde) {
			Transferable transferable = null;
			try {
				transferable = dtde.getTransferable();
			} catch (Exception e) {
				LogUtilities.error(e.getMessage(), e);
			}
			if (transferable == null) {
				return;
			}
			DataFlavor[] dataFlavors = dtde.getCurrentDataFlavors();
			for (DataFlavor dataFlavor : dataFlavors) {
				// 如果拖拽的数据是当前树提供的则接收解析
				if (dataFlavor == TREE_SIMPLE_DRAG_STRING) {
					if (transferable.isDataFlavorSupported(TREE_SIMPLE_DRAG_STRING)) {
						Object[] transferData = new Object[0];
						try {
							// 从 transferable 获取数据根据DataFlavor
							transferData = (Object[]) transferable.getTransferData(TREE_SIMPLE_DRAG_STRING);
						} catch (UnsupportedFlavorException | IOException e) {
							e.printStackTrace();
						}
						StringBuilder stringBuilder = new StringBuilder();
						for (Object transferDatum : transferData) {
							if (stringBuilder.length() > 0) {
								stringBuilder.append(",");
							}
							stringBuilder.append(transferDatum.toString());
						}
						UICommonToolkit.showMessageDialog(stringBuilder.toString());
					}
				}
			}
		}
	}
}
